package com.xuecheng.media.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mysql.jdbc.log.Log;
import com.xuecheng.api.media.model.dto.MediaDTO;
import com.xuecheng.api.media.model.qo.QueryMediaModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.common.ResourceTypeEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.media.common.constant.MediaErrorCode;
import com.xuecheng.media.common.utils.AliyunVODUtil;
import com.xuecheng.media.controller.MediaAuditController;
import com.xuecheng.media.controller.MediaController;
import com.xuecheng.media.convert.MediaConvert;
import com.xuecheng.media.entity.Media;
import com.xuecheng.media.mapper.MediaMapper;
import com.xuecheng.media.service.MediaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 媒资信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class MediaServiceImpl extends ServiceImpl<MediaMapper, Media> implements MediaService {



    /*
     * 实现步骤：
     *   1.是否需要开启事务（查询不需要开启，增删改时需要开启事务）
     *   2.判断关键数据（代码健壮性）
     *       关键数据：数据来源是前端
     *           分页数据需要判断：pageNo、pageSize
     *           查询添加对象数据不需要判断
     *   3.构建Page（MP）对象
     *   4.构建查询构建对象
     *   5.查询数据
     *       分页对象Page
     *       查询构建对象
     *   6.将查询结果封装并返回
     * */
    public PageVO queryMediaList(PageRequestParams params, QueryMediaModel model, Long companyId) {

        // 2.判断关键数据（代码健壮性）
        //      关键数据：数据来源是前端
        //          分页数据需要判断：pageNo、pageSize
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }

        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        //  3.构建Page（MP）对象
        Page<Media> page = new Page<>(params.getPageNo(), params.getPageSize());

        //  4.构建查询构建对象
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();

        if (StringUtil.isNotBlank(model.getFilename())) {
            queryWrapper.like(Media::getFilename, model.getFilename());
        }
        if (StringUtil.isNotBlank(model.getAuditStatus())) {
            queryWrapper.eq(Media::getAuditStatus, model.getAuditStatus());
        }
        queryWrapper.eq(Media::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        queryWrapper.eq(Media::getCompanyId, companyId);
        queryWrapper.orderByDesc(Media::getCreateDate);

        //  5.查询数据
        //      分页对象Page
        //      查询构建对象
        Page<Media> pageResult = this.page(page, queryWrapper);

        List<Media> records = pageResult.getRecords();
        long total = pageResult.getTotal();

        List<MediaDTO> dtos = Collections.EMPTY_LIST;
        if (!(CollectionUtils.isEmpty(records))) {
            dtos = new ArrayList<>();
            dtos = MediaConvert.INSTANCE.entitys2dtos(records);
        }

        //  6.将查询结果封装并返回-->PageVO
        PageVO pageVO = new PageVO<>(dtos, total, params.getPageNo(), params.getPageSize());

        return pageVO;
    }

    @Transactional
    public MediaDTO createMedia(MediaDTO dto) {
        //1.判断关键
        if (ObjectUtils.isEmpty(dto.getCompanyId())||
                StringUtil.isBlank(dto.getFilename())||
                StringUtil.isBlank(dto.getFileId())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 2.给信息数据赋值默认值(auditStatus设为未审核)
        dto.setAuditStatus(AuditEnum.AUDIT_UNPAST_STATUS.getCode());
        // 3.保存信息
        Media media = MediaConvert.INSTANCE.dto2entity(dto);
        boolean result = this.save(media);
        if (!result) {
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }
        // 4.将数据库最新数据返回
        Media po = this.getById(media.getId());
        MediaDTO resultDTO = MediaConvert.INSTANCE.entity2dto(po);
        return resultDTO;
    }

    public String getPlayUrlByMediaId(Long mediaId, Long companyId) {
        //判断关键数据
        if (ObjectUtils.isEmpty(mediaId) || ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //构建查询对象
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getId, mediaId);
        if (ObjectUtils.nullSafeEquals(companyId, MediaController.OPERATION_FLAG)) {
            queryWrapper.eq(Media::getCompanyId, companyId);
        }
        Media media = this.getOne(queryWrapper);
        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }
        //获得媒资文件url
        String type = media.getType();

        String url = null;

        if (ResourceTypeEnum.VIDEO.getCode().equals(type)) {
            url = getAliyunVodPlayUrl(media.getFileId());
        } else if (ResourceTypeEnum.DOCUMENT.getCode().equals(type)){

        } else if (ResourceTypeEnum.WORK.getCode().equals(type)) {

        }
        return url;
    }

    @Value("cn-shanghai")
    private String region;
    @Value("LTAI5tPM3UeS53rWcedrJX2B")
    private String accessKeyId;
    @Value("KsAsIAoiCBcO77e0jCAt7pUat8F08f")
    private String accessKeySecret;

    private String getAliyunVodPlayUrl(String fileId) {
        String playUrl = null;
        try {
            DefaultAcsClient client = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);
            GetPlayInfoResponse playInfo = AliyunVODUtil.getPlayInfo(client, fileId);
            List<GetPlayInfoResponse.PlayInfo> playInfoList = playInfo.getPlayInfoList();

            if (CollectionUtils.isEmpty(playInfoList)) {
                ExceptionCast.cast(MediaErrorCode.E_140018);
            }
            playUrl = playInfoList.get(0).getPlayURL();
        } catch (Exception e) {
            log.error(MediaErrorCode.E_140012.getDesc() + "{}", e.getMessage());
            ExceptionCast.cast(MediaErrorCode.E_140012);
        }
        return playUrl;
    }

    @Transactional
    public void removeMediaById(Long mediaId, Long companyId) {
        if (ObjectUtils.isEmpty(mediaId) || ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        Media media = this.getById(mediaId);
        //判断关键数据
        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }
        if (!(ObjectUtils.nullSafeEquals(media.getCompanyId(), companyId))) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        //判断业务数据
        String auditStatus = media.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)) {
            ExceptionCast.cast(MediaErrorCode.E_140017);
        }
        //删除媒资信息
        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Media::getStatus, CommonEnum.DELETE_FLAG.getCodeInt());
        updateWrapper.set(Media::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(Media::getId, mediaId);

        boolean result = this.update(updateWrapper);

        if (!result) {
            ExceptionCast.cast(MediaErrorCode.E_140002);
        }

    }

    public RestResponse<MediaDTO> getById4s(Long mediaId) {
        //判断关键数据
        if (ObjectUtils.isEmpty(mediaId)) {
            return RestResponse.validfail(CommonErrorCode.E_100101);
        }
        //判断业务数据
        Media media = this.getById(mediaId);
        if (ObjectUtils.isEmpty(media)) {
            return RestResponse.validfail(CommonErrorCode.E_100104);
        } else {
            MediaDTO mediaDTO = MediaConvert.INSTANCE.entity2dto(media);
            return RestResponse.success(mediaDTO);
        }
    }

    public PageVO queryMediaByPage(PageRequestParams params, QueryMediaModel model, Long companyId) {

        // 2.判断关键数据（代码健壮性）
        //      关键数据：数据来源是前端
        //          分页数据需要判断：pageNo、pageSize
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }

        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        //  3.构建Page（MP）对象
        Page<Media> page = new Page<>(params.getPageNo(), params.getPageSize());

        //  4.构建查询构建对象
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();

        if (StringUtil.isNotBlank(model.getFilename())) {
            queryWrapper.like(Media::getFilename, model.getFilename());
        }
        if (StringUtil.isNotBlank(model.getAuditStatus())) {
            queryWrapper.eq(Media::getAuditStatus, model.getAuditStatus());
        }
        if (!ObjectUtils.nullSafeEquals(companyId, MediaAuditController.OPERATION_FLAG)) {
            queryWrapper.eq(Media::getCompanyId, companyId);
        }
        queryWrapper.eq(Media::getStatus, CommonEnum.USING_FLAG.getCodeInt());

        queryWrapper.orderByDesc(Media::getCreateDate);

        //  5.查询数据
        //      分页对象Page
        //      查询构建对象
        Page<Media> pageResult = this.page(page, queryWrapper);

        List<Media> records = pageResult.getRecords();
        long total = pageResult.getTotal();

        List<MediaDTO> dtos = Collections.EMPTY_LIST;
        if (!(CollectionUtils.isEmpty(records))) {
            dtos = new ArrayList<>();
            dtos = MediaConvert.INSTANCE.entitys2dtos(records);
        }

        //  6.将查询结果封装并返回-->PageVO
        PageVO pageVO = new PageVO<>(dtos, total, params.getPageNo(), params.getPageSize());

        return pageVO;
    }

    public void approveMedia(MediaDTO dto) {
        //判断关键数据

        if (StringUtil.isBlank(dto.getAuditMind()) ||
                StringUtil.isBlank(dto.getAuditStatus()) ||
                ObjectUtils.isEmpty(dto.getId())) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //2.判断业务数据
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getId , dto.getId());
        queryWrapper.eq(Media::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        queryWrapper.eq(Media::getAuditStatus, CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode());
        int count = this.count(queryWrapper);
        if (count == 1) {
            ExceptionCast.cast(CommonErrorCode.E_100104);
        }
        String auditStatus = dto.getAuditStatus();
//        if (auditStatus.equals(CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode()) ||
//                auditStatus.equals(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode()) ||
//                auditStatus.equals(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode())) {
//            ExceptionCast.cast(MediaErrorCode.E_140017);
//        }
        //3.修改媒资审核信息
        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Media::getAuditStatus, dto.getAuditStatus());
        updateWrapper.set(Media::getAuditMind, dto.getAuditMind());

        updateWrapper.set(Media::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(Media::getId, dto.getId());

        boolean result = this.update(updateWrapper);
        if (!result) {
            ExceptionCast.cast(CommonErrorCode.E_100104);
        }

    }
}
